package com.example.java_gobang2.service;

import com.volcengine.ark.runtime.model.completion.chat.ChatCompletionRequest;
import com.volcengine.ark.runtime.model.completion.chat.ChatMessage;
import com.volcengine.ark.runtime.model.completion.chat.ChatMessageRole;
import com.volcengine.ark.runtime.service.ArkService;
import okhttp3.ConnectionPool;
import okhttp3.Dispatcher;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

@Component
public class AIService {
    // 从环境变量获取API密钥（安全实践推荐）
    static String apiKey = System.getenv("ARK_API_KEY");

    // 配置HTTP连接池（最大5个空闲连接，保持1秒）
    static ConnectionPool connectionPool = new ConnectionPool(5, 1, TimeUnit.SECONDS);

    // 配置请求调度器（管理异步请求队列）
    static Dispatcher dispatcher = new Dispatcher();

    // 构建ARK服务实例
    static ArkService service = ArkService.builder()
            .dispatcher(dispatcher)           // 设置调度器
            .connectionPool(connectionPool)   // 设置连接池
            .baseUrl("https://ark.cn-beijing.volces.com/api/v3") // API端点
            .apiKey(apiKey)                   // 注入API密钥
            .build();

    public String ai(String str) {
        List<ChatMessage> messages = new ArrayList<>();
        ChatMessage systemMessage = ChatMessage.builder()
                .role(ChatMessageRole.SYSTEM)  // 消息角色类型
                .content("你是一个五子棋大师,我会发一个棋盘给你,2代表你的棋子,1代表敌人的棋子,0代表还没棋子,你现在要下的棋子是2,你不能和我下在同一个地方,第一行是0,第二行是1," +
                        "第一列是0,第二列是1,告诉我你要下哪里,用坐标告诉我就行,如0,0 是左上角第一个棋子,这里没有任何限制,谁最快能连起来5个就赢," +
                        "你的输出格式如下 0,0,请不要进行任何说明只需要按照格式输出你的坐标")
                .build();

        ChatMessage userMessage = ChatMessage.builder()
                .role(ChatMessageRole.USER)
                .content(str)
                .build();

        messages.add(systemMessage);
        messages.add(userMessage);

        ChatCompletionRequest chatCompletionRequest = ChatCompletionRequest.builder()
                .model("ep-20250218141256-qk8w9")  // 指定模型ID ep-20250215182442-99m6v (R1 感觉被降智了 思考很久) ep-20250218141256-qk8w9 (R3 弱智一号)  ep-20250306195315-6xsbl (弱智二号)
                .messages(messages)                 // 设置对话历史
                .build();

        String res = service.createChatCompletion(chatCompletionRequest)
                .getChoices().get(0).getMessage().getContent().toString();
        System.out.println(res);
        return res;

    }

    public void ai2(String str) {
        List<ChatMessage> messages = new ArrayList<>();
        ChatMessage systemMessage = ChatMessage.builder()
                .role(ChatMessageRole.SYSTEM)  // 消息角色类型
                .content("你是一个五子棋大师,我会发一个棋盘给你,2代表你的棋子,1代表敌人的棋子,0代表还没棋子,你现在要下的棋子是2,你不能和我下在同一个地方,第一行是0,第二行是1," +
                        "第一列是0,第二列是1,告诉我你要下哪里,用坐标告诉我就行,如0,0 是左上角第一个棋子,你的输出格式如下 0,0,请不要进行任何说明只需要按照格式输出你的坐标")
                .build();

        ChatMessage userMessage = ChatMessage.builder()
                .role(ChatMessageRole.USER)
                .content(str)
                .build();

        messages.add(systemMessage);
        messages.add(userMessage);

        ChatCompletionRequest chatCompletionRequest = ChatCompletionRequest.builder()
                .model("ep-20250218141256-qk8w9")  // 指定模型ID
                .messages(messages)                 // 设置对话历史
                .build();

        service.createChatCompletion(chatCompletionRequest)
                .getChoices()  // 获取响应选项列表
                .forEach(choice ->
                        System.out.println(choice.getMessage().getContent())
                );

    }

    // 定义各种棋型的分数
    private static final int FIVE = 100000;       // 连五，必胜
    private static final int LIVE_FOUR = 10000;   // 活四
    private static final int DEAD_FOUR = 1000;    // 冲四
    private static final int LIVE_THREE = 1000;   // 活三
    private static final int DEAD_THREE = 100;    // 眠三
    private static final int LIVE_TWO = 100;      // 活二
    private static final int DEAD_TWO = 10;       // 眠二
    
    // 八个方向：水平、垂直、对角线
    private static final int[][] DIRECTIONS = {
            {-1, 0}, {1, 0},   // 垂直方向
            {0, -1}, {0, 1},   // 水平方向
            {-1, -1}, {1, 1},  // 主对角线
            {-1, 1}, {1, -1}   // 副对角线
    };
    
    // 搜索深度
    private static final int MAX_DEPTH = 3;
    
    public int[] ai3(int[][] chessBoard, int row, int col) {
        // 最佳落子位置
        int[] bestMove = new int[2];
        
        // 如果是第一次落子，选择靠近玩家棋子的位置
        if (isEmpty(chessBoard)) {
            bestMove[0] = row;
            bestMove[1] = col + 1;
            if (bestMove[1] >= chessBoard[0].length) {
                bestMove[1] = col - 1;
            }
            return bestMove;
        }
        
        // 使用极小极大算法寻找最佳落子位置
        int bestScore = Integer.MIN_VALUE;
        
        // 遍历棋盘所有空位
        for (int i = 0; i < chessBoard.length; i++) {
            for (int j = 0; j < chessBoard[0].length; j++) {
                // 只考虑空位
                if (chessBoard[i][j] == 0) {
                    // 只考虑周围有棋子的空位，提高搜索效率
                    if (hasNeighbor(chessBoard, i, j, 2)) {
                        // 模拟AI下棋
                        chessBoard[i][j] = 2;
                        
                        // 计算此步棋的分数
                        int score = minimax(chessBoard, MAX_DEPTH, false, Integer.MIN_VALUE, Integer.MAX_VALUE, row, col);
                        
                        // 撤销此步棋
                        chessBoard[i][j] = 0;
                        
                        // 更新最佳分数和落子位置
                        if (score > bestScore) {
                            bestScore = score;
                            bestMove[0] = i;
                            bestMove[1] = j;
                        }
                    }
                }
            }
        }
        
        // 返回最佳落子位置
        return bestMove;
    }
    
    // 极小极大算法，带Alpha-Beta剪枝
    private int minimax(int[][] chessBoard, int depth, boolean isMaximizing, int alpha, int beta, int lastRow, int lastCol) {
        // 如果达到最大深度或者游戏结束，返回评估分数
        if (depth == 0 || isGameOver(chessBoard)) {
            return evaluateBoard(chessBoard);
        }
        
        if (isMaximizing) {
            // AI最大化得分
            int maxScore = Integer.MIN_VALUE;
            
            for (int i = 0; i < chessBoard.length; i++) {
                for (int j = 0; j < chessBoard[0].length; j++) {
                    if (chessBoard[i][j] == 0 && hasNeighbor(chessBoard, i, j, 2)) {
                        chessBoard[i][j] = 2; // AI落子
                        int score = minimax(chessBoard, depth - 1, false, alpha, beta, i, j);
                        chessBoard[i][j] = 0; // 撤销落子
                        
                        maxScore = Math.max(maxScore, score);
                        alpha = Math.max(alpha, score);
                        
                        if (beta <= alpha) {
                            // Beta剪枝
                            return maxScore;
                        }
                    }
                }
            }
            
            return maxScore;
        } else {
            // 玩家最小化得分
            int minScore = Integer.MAX_VALUE;
            
            for (int i = 0; i < chessBoard.length; i++) {
                for (int j = 0; j < chessBoard[0].length; j++) {
                    if (chessBoard[i][j] == 0 && hasNeighbor(chessBoard, i, j, 2)) {
                        chessBoard[i][j] = 1; // 玩家落子
                        int score = minimax(chessBoard, depth - 1, true, alpha, beta, i, j);
                        chessBoard[i][j] = 0; // 撤销落子
                        
                        minScore = Math.min(minScore, score);
                        beta = Math.min(beta, score);
                        
                        if (beta <= alpha) {
                            // Alpha剪枝
                            return minScore;
                        }
                    }
                }
            }
            
            return minScore;
        }
    }
    
    // 判断游戏是否结束
    private boolean isGameOver(int[][] chessBoard) {
        // 判断是否有一方获胜
        for (int i = 0; i < chessBoard.length; i++) {
            for (int j = 0; j < chessBoard[0].length; j++) {
                if (chessBoard[i][j] != 0) {
                    if (hasWon(chessBoard, i, j)) {
                        return true;
                    }
                }
            }
        }
        
        // 判断棋盘是否已满
        for (int i = 0; i < chessBoard.length; i++) {
            for (int j = 0; j < chessBoard[0].length; j++) {
                if (chessBoard[i][j] == 0) {
                    return false;
                }
            }
        }
        
        return true;
    }
    
    // 判断是否有一方获胜
    private boolean hasWon(int[][] chessBoard, int row, int col) {
        int player = chessBoard[row][col];
        
        // 检查四个方向（水平、垂直、两个对角线）
        for (int d = 0; d < 4; d++) {
            int count = 1;
            
            // 向一个方向延伸
            for (int i = 1; i < 5; i++) {
                int newRow = row + i * DIRECTIONS[d*2][0];
                int newCol = col + i * DIRECTIONS[d*2][1];
                
                if (isValidPosition(chessBoard, newRow, newCol) && chessBoard[newRow][newCol] == player) {
                    count++;
                } else {
                    break;
                }
            }
            
            // 向相反方向延伸
            for (int i = 1; i < 5; i++) {
                int newRow = row + i * DIRECTIONS[d*2+1][0];
                int newCol = col + i * DIRECTIONS[d*2+1][1];
                
                if (isValidPosition(chessBoard, newRow, newCol) && chessBoard[newRow][newCol] == player) {
                    count++;
                } else {
                    break;
                }
            }
            
            // 如果连成5个，则获胜
            if (count >= 5) {
                return true;
            }
        }
        
        return false;
    }
    
    // 评估整个棋盘
    private int evaluateBoard(int[][] chessBoard) {
        int score = 0;
        
        // 遍历所有位置
        for (int i = 0; i < chessBoard.length; i++) {
            for (int j = 0; j < chessBoard[0].length; j++) {
                if (chessBoard[i][j] == 2) {
                    // AI的棋子加分
                    score += evaluatePosition(chessBoard, i, j, 2);
                } else if (chessBoard[i][j] == 1) {
                    // 玩家的棋子减分
                    score -= evaluatePosition(chessBoard, i, j, 1);
                }
            }
        }
        
        return score;
    }
    
    // 评估某个位置的分数
    private int evaluatePosition(int[][] chessBoard, int row, int col, int player) {
        int score = 0;
        
        // 检查八个方向
        for (int d = 0; d < 4; d++) {
            score += evaluateDirection(chessBoard, row, col, player, DIRECTIONS[d*2][0], DIRECTIONS[d*2][1]);
            score += evaluateDirection(chessBoard, row, col, player, DIRECTIONS[d*2+1][0], DIRECTIONS[d*2+1][1]);
        }
        
        return score;
    }
    
    // 评估某个方向的分数
    private int evaluateDirection(int[][] chessBoard, int row, int col, int player, int rowDir, int colDir) {
        // 统计连子数和空位数
        int count = 1;  // 当前位置已有一个棋子
        int empty = 0;
        int block = 0;
        
        // 向一个方向查找
        for (int i = 1; i < 5; i++) {
            int newRow = row + i * rowDir;
            int newCol = col + i * colDir;
            
            if (!isValidPosition(chessBoard, newRow, newCol)) {
                block++;
                break;
            }
            
            if (chessBoard[newRow][newCol] == player) {
                count++;
            } else if (chessBoard[newRow][newCol] == 0) {
                empty++;
                break;
            } else {
                block++;
                break;
            }
        }
        
        // 向相反方向查找
        for (int i = 1; i < 5; i++) {
            int newRow = row - i * rowDir;
            int newCol = col - i * colDir;
            
            if (!isValidPosition(chessBoard, newRow, newCol)) {
                block++;
                break;
            }
            
            if (chessBoard[newRow][newCol] == player) {
                count++;
            } else if (chessBoard[newRow][newCol] == 0) {
                empty++;
                break;
            } else {
                block++;
                break;
            }
        }
        
        // 根据连子数、空位数和阻挡数计算分数
        return getScore(count, empty, block);
    }
    
    // 根据连子数、空位数和阻挡数计算分数
    private int getScore(int count, int empty, int block) {
        // 两端都被阻挡
        if (block == 2 && empty == 0) {
            return 0;
        }
        
        // 连五
        if (count >= 5) {
            return FIVE;
        }
        
        // 活四或者冲四
        if (count == 4) {
            if (empty == 2) {
                return LIVE_FOUR;  // 活四
            } else {
                return DEAD_FOUR;  // 冲四
            }
        }
        
        // 活三或者眠三
        if (count == 3) {
            if (empty == 2) {
                return LIVE_THREE;  // 活三
            } else {
                return DEAD_THREE;  // 眠三
            }
        }
        
        // 活二或者眠二
        if (count == 2) {
            if (empty == 2) {
                return LIVE_TWO;  // 活二
            } else {
                return DEAD_TWO;  // 眠二
            }
        }
        
        return 0;
    }
    
    // 判断位置是否有效
    private boolean isValidPosition(int[][] chessBoard, int row, int col) {
        return row >= 0 && row < chessBoard.length && col >= 0 && col < chessBoard[0].length;
    }
    
    // 判断是否有相邻棋子
    private boolean hasNeighbor(int[][] chessBoard, int row, int col, int distance) {
        for (int i = Math.max(0, row - distance); i <= Math.min(chessBoard.length - 1, row + distance); i++) {
            for (int j = Math.max(0, col - distance); j <= Math.min(chessBoard[0].length - 1, col + distance); j++) {
                if (chessBoard[i][j] != 0) {
                    return true;
                }
            }
        }
        return false;
    }
    
    // 判断棋盘是否为空
    private boolean isEmpty(int[][] chessBoard) {
        for (int i = 0; i < chessBoard.length; i++) {
            for (int j = 0; j < chessBoard[0].length; j++) {
                if (chessBoard[i][j] != 0) {
                    return false;
                }
            }
        }
        return true;
    }
}
